\documentclass[a4paper]{article}
\usepackage[french]{babel}
\usepackage[utf8]{inputenc}

\usepackage[top=3cm, bottom=3cm, left=3.5cm, right=3.5cm]{geometry}



\begin{document}

\title{Application d'échange de Fichier en Pair à Pair\\ Rapport du
  groupe 1}

\author{Aylli \bsc{Chuquillanqui}, Emilien \bsc{Dupont}, Taha \bsc{Najar},\\
 Cyrille \bsc{Piacibello}, Nicolas \bsc{Verdier}}

\maketitle
\newpage
\section*{Introduction}
Ce projet consiste à développer une application pour le partage de
fichier en mode pair à pair. Les machines du réseau sont dans cette
configuration à la fois serveur et client. Elles peuvent demander des
fichiers aux autres, ou partager leurs données. Il est question de
faire appel à un Tracker qui sera chargé d'aider les pairs dans la
recherche de fichier. Il s'agit en fait de la version centralisée du
problème. Chaque pair s'identifiera donc au tracker, puis lui indiquera
les fichiers qu'il possède et les fichiers qu'il veux. Le tracker
répond alors en indiquant qui possède les fichiers demandés.

Nous présenterons en premier lieu notre implémentation du client, puis
celle du tracker.

\section*{Avant-propos}
Nous avons choisi de faire la partie client en Java et le Tracker en
C. Ce choix s'est imposé au moment ou la réalisation d'une version
décentralisée était demandée. En effet, le Java offre des possibilités
de réutilisation de code intéressantes, ce qui nous aurait permis de
reprendre une partie de notre travail dans la version distribuée.

\newpage

\section{Client}

\subsection{Architecture de l'arborescence du programme}

Le client se base sur son fichier de configuration et sur deux
dossiers qui contiennent les fichiers en cours de téléchargement et
partagés. Le fichier de configuration principal du client donne les
informations nécessaires à la connexion au Tracker :
\begin{itemize}
\item adresse IP du Tracker
\item port utilisé pour la connection
\end{itemize}

Ainsi que quelques configurations internes au client :
\begin{itemize}
\item intervalle de mise à jour des buffermaps (envoi aux pairs et au Tracker)
\item taille des pièces de fichier par défaut
\item le nombre maximum de connexions simultanées avec des pairs
\item le chemin du dossier seeds
\item le chemin du dossier leeches
\item le nombre de pièces maximum à demander par connexion
\end{itemize}

Deux fichiers de configuration supplémentaires sont présents dans les
dossiers seeds et leeches. Ils permettent de stocker les informations
sur les fichiers en cours de téléchargement ou partagés. Pour chaque
fichier présent dans ces dossiers, la taille des pièces est stockée
dans ces deux fichiers de configuration. Si un fichier est présent en
partage mais qu'il n'apparaît pas dans le fichier de configuration, la
taille des pièces de fichier par défaut entre en jeu et est ajoutée au
fichier de configuration (cela signifie que le client est le seul
propriétaire du fichier actuellement sur le réseau).


Pour toutes les manipulations de configurations, nous avons utilisé
\textit{java.util.Properties} qui permet une gestion de fichiers de
configuration très simple en utilisant la méthode
\textit{getProperty(String)}.

\subsection{Parsing des fichiers}

Une classe \textit{Fichiers} parse les répertoires leeches et seeds et
répertorie tous les fichiers qu'ils contiennent avec leur nom, taille,
taille de leurs pièces par défaut ainsi que leur clé.  

La clé est générée gràce à l'algorithme MD5, qui permet de créer une
clé unique de 32 octets associée à un fichier. Cette clé n'est ici pas
générée uniquement à partir du nom du fichier mais aussi à partir de
son contenu. Ceci nous permet d'avoir deux fichiers différents de même
nom sur le réseau.

Pour le buffermap, nous avons utilisé un \textit{BitSet} associé à un
tableau de \textit{FilePart} (la classe contenant les données des
fichiers). Cependant, lors du transfert du buffermap d'un fichier (par
exemple lors d'un \textit{have}) nous avons dû calculer la taille du
buffermap à l'aide de la taille totale du fichier (récupérée lors de
la réponse au \textit{look}), de la taille des pièces et du nombre de
pièces.

\subsection{Gestion des communications réseau}

Lors de leurs lancement, les clients font un \textit{announce} au
tracker pour lui lister les seeds et leeches qu'il a à sa disposition.
Les clients font ensuite régulièrement des \textit{update} au tracker
afin de mettre à jour leur liste de fichiers.  Chaque client écoute en
permanence un port dans un thread dédié afin de pouvoir envoyer son
\textit{BufferMap} lorsqu'il reçoit une requête \textit{interested}
d'un autre client, ou envoyer les données binaires d'un fichier après
réception d'une requête \textit{getpieces}.

\newpage
\subsection{Choix des pairs sollicités}

L'algorithme de téléchargement mis en place par le client est simple
mais permet de répartir la charge sur un maximum de clients : On
stocke dans une liste pour chaque client qui a des bouts de fichiers
les parties que l'on souhaite lui demander en essayant de répartir sur
tous les clients. Si une partie du fichier est possédée par plusieurs
clients, on demandera en priorité aux clients les moins solicités. Une
fois qu'une liste associée à un client compte le bon nombre de pièces
(ce nombre peut être rêglé dans le fichier config.cfg), on envoie les
requêtes \textit{getpieces} aux clients, on réceptionne les données, on
les écrit dans un fichier au bon offset et on modifie notre
BufferMap. On itère ainsi sur tous les index non possédés pour obtenir
le fichier complet.

Il aurait été intéressant de réfléchir sur un algorithme évolutif, qui
prendrait en compte les modifications de répartitions des fichiers en
temps réel. C'est-à-dire que le client pourrait demander de nouvelles
pièce du fichiers à des utilisateurs qui ne les avaient pas au début
du transfert de données. Ce problème est très complexe d'un point de
vue algorithmique, et nous n'avons pas eu le temps de nous y
intéresser.


\section{Tracker}
\subsection{Types abstraits de données utilisés}
Afin de pouvoir gérer les informations concernant les clients
et les fichiers référencés, nous avons implémenté différentes
structures. La structure principale, qui nous permet de faire le lien
entre nos clients et les fichiers qu'ils possèdent est une table de
hashage, nommée \verb?hash_table? construite de la façon suivante :

\begin{center}
  \begin{tabular}{| c | c |}
    \hline
    Nom du champs & Type du champs \\
    \hline
    Tableaux de fichier  & Pointeur vers les structures de fichier\\
    Possesseur & Matrice d'entiers \\
    Nombre de fichier & Entier \\
    Nombre de client & Entier\\
    Tableaux des clients & Pointeur vers les structures de clients du réseau\\
    \hline
  \end{tabular}
\end{center}

La table de hashage nous est apparu comme nécessaire pour déterminer
quels clients du réseau, possèdent quels fichiers. Ainsi grâce à la
matrice des possesseurs, nous pouvons répondre au plus vite à ce genre
de question : Tableau [indice du client] [indice du fichier] =
vrai/faux (selon si le client possède le fichier ou non). Il est à
noter que nous accédons à la clé du client de la façon suivante :
Tableau[client][0] = clef du client. 

Nous avons donc implémenté les fonctions d'accés et de modifications
comme l'ajout de fichier et de client. La matrice possesseur est
allouée dynamiquement. À chaque ajout de fichier ou de client, nous
sommes obligé de la réallouer, avec un appel à \verb?realloc?. Cette
opération, bien que lourde, puisque la matrice est recopiée dans le
cas ou l'espace disponible est insuffisant, nous a paru une meilleure
solution que l'uage d'une matrice de taille fixe, qui aurait été
limitant en terme de nombre de client et de fichier.

Nous avons été également amenés à définir la structure \verb?client?
suivante :
\begin{center}
  \begin{tabular}{| c | c |}
    \hline
    Nom du champs & Type du champs \\
    \hline
    Clef du client & Entier \\
    IP & Chaine de caractères\\
    Port & Entier\\ 
    \hline
  \end{tabular}
\end{center}

De même, la structure \verb?fichier? est définie comme suit :
\begin{center}
  \begin{tabular}{| c | c |}
    \hline
    Nom du champs & Type du champs \\
    \hline
    Taille du fichier & Entier \\
    Taille des pièces & Entier\\
    Clef (du fichier) & Entier\\ 
    \hline
  \end{tabular}
\end{center}

\subsection{Problématique réseau}

Le sujet imposait l'usage du protocole \verb?TCP/IP?. Nous avons donc
réutilisé les cours de système et de réseau, ainsi que le td de réseau
ou nous avons manipulé les sockets pour la première fois. Dans le but
de maintenir tout les clients connectés, nous maintenons un tableau de
sockets qui sont initialisées à chaque fois qu'un nouveau client se
connecte. Ces sockets sont créees avec le domaine \verb?AF_INET?, et
sont de type \verb?SOCK_STREAM?. Le domaine \verb?AF_INET? est utilisé
puisque notre application doit être utilisable sur internet, et
utilise le protocole \verb?IPv4?. Nous utilisons le type
\verb?SOCK_STREAM? pour garantire l'intégrité des données
transmises. En effet, si un bloc n'est pas transmis dans un
certain délai la socket est considérées comme inutilisable. 
 
\subsection{Architecture du tracker}

Le tracker doit pouvoir fonctionner avec plusieur clients
connectés. En effet, il n'y a que peu d'intérêt à implémenter un
réseau de partage pair à pair ne permettant pas de gérer plusieurs
clients. Nous nous sommes donc orienté vers une architecture avec
plusieurs threads. À chaque nouvelle connexion d'un client, nous lui
attribuons un thread, qui va lire les informations reçues et répondre
ensuite aux demandes avant de fermer la connexion.

Le Tracker est toujours en écoute afin de pouvoir servir au mieux les
clients.  Pour ce faire, la table de hashage est compris dans une
structure serveur nommée \verb?serv?. Nous avons ainsi la structure
suivante :\\

\begin{center}
  \begin{tabular}{| c | c |}
    \hline
    Nom du champs & Type du champs \\
    \hline
    Hash\_table & Pointeur sur la table de hashage \\
    Sock & Entier correspondant à la socket utilisée\\
    Client c & Pointeur sur un client\\ 
    \hline
  \end{tabular}
\end{center}

Quand un nouveau client se connecte au Tracker, un nouveau thread est
créé.  Ainsi pour chaque client, le Tracker lui fournit une structure
serveur dans laquelle, la table de hashage est commune à tous. 

Chaque client a une socket propre, qui sert à la communication entre
le client et le Tracker. Nous avons evidemment eu un problème de
partage de variables. En effet, chaque thread lit et modifie la table
de hashage. Pour régler ce problème, nous avons alors mis en place un
mutex, utilisé sur chaque thread. De cette manière, le traitement de
chaque demande empêchera tout autre traitement en parallele.  Cela
ralentit considérablement le fonctionnement de notre tracker, mais
nous n'avons pas eu le temps de réflechir à une architecture plus
efficace.

\subsection{Gestion des requêtes des utilisateurs}

Le reste de l'implémentation consiste donc à gérer les messages
envoyés par les clients au Tracker. Il faut en effet à la fois pouvoir
répondre aux demandes des clients, mais aussi actualiser les
informations recueillies sur les fichiers disponibles et les clients
connectés. Pour cela, nous avons décidé d'utiliser un parseur afin de
pouvoir récupérer les informations nécessaires. Ainsi à chaque espace
ou crochet, les informations sont récupérées à l'aide des fonctions
$strtok$ et $sscanf$. Puis selon le type d'information, le parseur
actualise la table de hashage et envoie le message correspondant au
client. Le Tracker sait ainsi de façon périodique où se trouvent les
fichiers.

L'ensemble des fonctions correspondantes font partie du fichier
\verb?parseur.c?.

\subsection{Remarques}

Il est à noter que nous avons imposé un nombre limité de clients. De
plus, la partie Tracker est gourmande en espace mémoire.  En effet,
nous avons fait beaucoup d'allocations pour permettre aux sockets
d'être toujours disponible. Par exemple, à chaque nouvelle connexion,
on alloue l'espace correspondant à la socket.

\section{État d'avancement du projet} 

Le projet n'est pas terminé. En effet il reste des problèmes non
résolus.

Nous avons effectué les test unitaire sur la partie client gràce à un
tracker réalisé par un autre groupe. Nos tests se sont limités au cas
de seulement deux utilisateurs qui souhaitent se transmettre un
fichier. Ce transfert ne respecte pas l'intégrité du fichier, sa taille
notament est modifié.

Nous n'avons pas non plus mis en place une interface
graphique pour l'application client. Il nous a paru plus intéressant
de résoudre les problèmes liés à l'implémentation des fonctionalités
réseau.

Concernant la partie tracker, il reste des dysfonctionnements:
\begin{itemize}
\item Lors d'une requête de type \verb?getfile?, le tracker répond
  bien en renvoyant l'adresse \verb?IP? d'un pair ayant le fichier,
  néanmoins la chaine de caractère reçu par l'utilisateur est parfois
  corrompu. De plus, si le tracker reçoit à nouveau une demande
  téléchargement, il cesse de fonctionner.
\item Notre implémentation ne supporte que peu d'utilisateurs
  connectés simultanément.
\end{itemize}

Pour finir notre phase d'intégration des parties tracker et client a
été difficile. Nous nous sommes rendu compte de certaines différences
d'interprétation du sujet. Par exemple, nous n'avions pas la même
convention concernant les identifiants des fichiers. Ceux-ci étaient
considérés comme des entiers dans le tracker tandis que le client
utilisait un code \verb?MD5?. Nous avons donc perdu du temps en
réécrivant les fonctions de recherche et d'ajout de fichiers. De même
il existe des divergences dans les fonctionnalités implémentées. Le
tracker peut réaliser une recherche de fichier en fonction de la
taille (suite à une requête de type \verb?look [filesize>"1048576"]?),
mais le client n'implémente pas cette recherche.

\newpage


\section{Conclusion}

Ce projet n'est que partielement terminé. Néanmoins il nous a permis,
dans une certaine mesure, de se confronter à des problématiques de
réseau.

Nous avons également rencontré des difficultés là où nous ne les
attendions pas.

Nous avons eu des problèmes lors des tests effectués avec le client à
cause de la redirection de port. En effet celle-ci a souvent eu des
problèmes et cela nous a empêché de tester lors de séances de code.

De plus, lors de l'implémentation de la partie client, le logiciel
Eclipse nous a posé certains problèmes, comme la configuration du
logiciel ou encore les workspaces. Il a donc été nécessaire de passer
du temps à configurer, voir à modifier le buildpath.

Vis à vis de la partie Tracker, cela nous a pris du temps de
conceptualiser notre Tracker. Ainsi s'est posé le problème de faire ou
non une hashtable. Cela nous a fait perdre un temps précieux à nous
lancer correctement dans le sujet. De plus, nous avions envisagé une
hashtable plus complète mais qui aurait pris plus de place et imposé
une gestion plus importante. Nous avons donc dû remanier plusieurs
fois notre hashtable.

Finalement, les difficultés rencontrés au cours de ce projet ont
concerné autant l'aspect réseau que l'aspects programmation.

\end{document}
